/**
 * Created with IntelliJ IEDA.
 * Description:
 * User:86186
 * Date:2022-09-19
 * Time:10:21
 */

/**
 *  阻塞队列
 *  优先级队列实现
 */
class MyBlockqueue{
    //volatile:防止指令重排序和内存可见性问题
    private volatile int[] item = new int[1000];
    //头元素
    private volatile int head = 0;
    //实时跟踪元素的下标
    private volatile int cur = 0;
    //数组中元素的个数
    private volatile int UsedSize = 0;

    //入队列
    public void put(int val) throws InterruptedException {
        //加锁
        synchronized (this){
            //判断数组是否已满,满则释放锁,等待到take()完成后notify()
            while (UsedSize >= item.length){
                this.wait();
            }
            item[cur] = val;
            cur++;
            //当cur的值达到数组长度的最大值时,需要重返0下标
            if(cur >= item.length){
                cur = 0;
            }
            UsedSize++;
            //针对take()操作的notify
            this.notify();
        }
    }

    //出队列,返回删除的元素的内容
    public Integer take() throws InterruptedException {
        synchronized(this){
            //当数组中没有元素时,无法执行take()操作,则需要等待到put()操作完成后
            while (UsedSize == 0){
                this.wait();
            }
            int ret = item[cur];
            head++;
            //当head的值达到数组长度的最大值时,需要重返0下标
            if(head >= item.length){
                head = 0;
            }
            UsedSize--;
            //take()完成后notify,苏醒wait();
            this.notify();
            return ret;
        }
    }
}


public class Blockqueue {

    public static void main(String[] args) {
        MyBlockqueue queue = new MyBlockqueue();

        Thread producer = new Thread(() -> {
            int n = 1;
            while (true) {
                try {
                    queue.put(n);
                    System.out.println("生产元素 " + n);
                    n++;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread customer = new Thread(() -> {
            while (true) {
                try {
                    int n = queue.take();
                    System.out.println("消费元素 " + n);
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        producer.start();
        customer.start();


    }
}
